package com.augurit.wf.client.agency.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jbpm.api.ProcessInstance;
import org.jbpm.pvm.internal.task.TaskImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.orm.Page;
import org.springside.modules.orm.PropertyFilter;

import com.augurit.common.dao.OmUserDao;
import com.augurit.common.entity.OmUser;
import com.augurit.common.system.convert.OmUserConverter;
import com.augurit.common.system.web.org.form.OmUserForm;
import com.augurit.common.util.HqlUtils;
import com.augurit.common.util.PageUtils;
import com.augurit.common.util.lang.StringUtils;
import com.augurit.wf.bi.service.IWfBusTemplateService;
import com.augurit.wf.bi.web.form.WfBusTemplateForm;
import com.augurit.wf.client.agency.convert.WfAgencyConvertor;
import com.augurit.wf.client.agency.service.IWfAgencyService;
import com.augurit.wf.client.agency.web.form.WfAgencyForm;
import com.augurit.wf.common.dao.Jbpm4HistTaskDao;
import com.augurit.wf.common.dao.Jbpm4TaskDao;
import com.augurit.wf.common.dao.WfAgencyDao;
import com.augurit.wf.common.dao.WfAgencyDetailDao;
import com.augurit.wf.common.entity.Jbpm4HistTask;
import com.augurit.wf.common.entity.Jbpm4Task;
import com.augurit.wf.common.entity.WfAgency;
import com.augurit.wf.common.entity.WfAgencyDetail;
import com.augurit.wf.common.service.IWfService;

@Service
@Transactional
public class WfAgencyServiceImpl implements IWfAgencyService{

	@Autowired
	private WfAgencyDao wfAgencyDao;
	
	@Autowired
	private WfAgencyDetailDao wfAgencyDetailDao;
	
	@Autowired
	private OmUserDao omUserDao;
	
	@Autowired
	private IWfService wfService;

	@Autowired
	private Jbpm4TaskDao jbpm4TaskDao;
	
	@Autowired
	private Jbpm4HistTaskDao jbpm4HistTaskDao;
	
	@Autowired
	private IWfBusTemplateService wfBusTemplateService;
	
	/**
	 * 根据主键获取Form对象
	 */
	@Transactional(readOnly = true)
	public WfAgencyForm get(Long id) {
		if(id != null){
			WfAgency entity = wfAgencyDao.get(id);
			
			List<WfAgencyDetail> details = wfAgencyDetailDao.getBy(id);
			
			WfAgencyForm form = WfAgencyConvertor.convertVoToForm(entity);
		//	form.setAgentProcessList(form.formatAgentProcessList(details));
			form.setWfTemplateNames(getTemplateNames(details));
			form.setWfTemplateIds(form.formatWfTemplateIds(details));
			return form;
		}
		return null;
	}
	
	/**
	 * 删除Form对象列表
	 */
	public void delete(Long... ids) {
		wfAgencyDao.delete(ids);
	}

	/**
	 * 保存新增或修改的Form对象列表
	 */
	public void save(WfAgencyForm... forms) {
		if(forms != null)
			for(WfAgencyForm form : forms)
				this.save(form);
	}
	
	/**
	 * 保存新增或修改的Form对象
	 */
	public void save(WfAgencyForm form){
		
		if(form != null){
			WfAgency entity = null;
			
			//准备VO对象
			if(form != null && form.getId() != null){
				entity = wfAgencyDao.get(form.getId());
			}else{
				entity = new WfAgency();
			}
			
			//属性值转换
			WfAgencyConvertor.convertFormToVo(form, entity);
			
			//保存
			wfAgencyDao.save(entity);
			
			//回填ID属性值
			form.setId(entity.getId());
		}
	}

	/**
	 * 根据Form对象的查询条件作分页查询
	 */
	@Transactional(readOnly = true)
	public Page<WfAgencyForm> search(Page<WfAgencyForm> page, WfAgencyForm form) {
		// 建立新的分页对象
		Page pg = PageUtils.newPageInstance(page);
		
		// 查询语句及参数
		StringBuffer hql = new StringBuffer("from WfAgency ps where 1=1");
		List values = new ArrayList();
		
		// 查询条件
		if(form != null){
			if(form.getLoginUserCode() != null && form.getLoginUserCode().trim().length() > 0){
				hql.append(" and ps.principal = ?");
				values.add(form.getLoginUserCode());
			}
		}
		
		//排序
		hql.append(HqlUtils.buildOrderBy(page, "ps"));
		
		// 执行分页查询操作
		wfAgencyDao.findPage(pg, hql.toString(), values);
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<WfAgencyForm> list = null;
		if( pg.getResult() != null && pg.getResult().size() > 0){
			list = new ArrayList<WfAgencyForm>();
			
			for(int i = 0; i < pg.getResult().size(); i++){
				WfAgencyForm agencyform = WfAgencyConvertor.convertVoToForm((WfAgency)pg.getResult().get(i));
				
				List<WfAgencyDetail> details = wfAgencyDetailDao.getBy(agencyform.getId());
				String wfTemplateNames = getTemplateNames(details);
				//	agencyform.setAgentProcessList(agencyform.formatAgentProcessList(details));
				agencyform.setWfTemplateNames(wfTemplateNames);
				list.add(agencyform);
			}
		}
		PageUtils.copy(pg, list, page);
		return page;
	}
	
	/**
	 * 根据过滤条件列表作分页查询
	 */
	@Transactional(readOnly = true)
	public Page<WfAgencyForm> search(Page<WfAgencyForm> page, List<PropertyFilter> filters) {
		// 建立新的分页对象
		Page<WfAgency> pg = PageUtils.newPageInstance(page);
		
		// 按过滤条件分页查找对象
		wfAgencyDao.findPage(pg, filters);
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<WfAgencyForm> list = WfAgencyConvertor.convertVoListToFormList(pg.getResult());
		PageUtils.copy(pg, list, page);
		return page;
	}
	
	/**
	 * 根据agencyId清除JBPM4_TASK、WF_TASK_Summary中代理关系
	 * @param agencyId 代理主键id
	 */
	public void clearAgentCascade(WfAgencyForm form){
		if(form.getId() != null){
			//获取代理细节
			List<WfAgencyDetail> details = wfAgencyDetailDao.getBy(form.getId());
			
			if(details != null && details.size() > 0){
				for(WfAgencyDetail detail:details){
					//获取流程定义id获取其下的流程实例列表
					List<ProcessInstance> list = wfService.getProcInstsByTemplateId(detail.getWfTemplateId());
					
					if(list != null && list.size() > 0){
						for(ProcessInstance processInstance: list){
							//获取流程实例对应的task列表
							List<Jbpm4Task> tasks = jbpm4TaskDao.getByAssigneeAndProcessInstanceId(form.getPrincipal(), processInstance.getId());
							
							if(tasks != null && tasks.size() > 0){
								//清空每个task的代理
								for(Jbpm4Task task:tasks){
									jbpm4TaskDao.clearAgent(task);
									Jbpm4HistTask histTask = jbpm4HistTaskDao.get(task.getTaskInstDbid());
									jbpm4HistTaskDao.clearAgent(histTask);
								}
							}
							
//							//获取流程实例对应的summary列表
//							List<WfTaskSummary> summaries = wfTaskSummaryService.getByAssigneeAndProcessInstanceId(form.getPrincipal(), processInstance.getId());
//							
//							if(summaries != null && summaries.size() > 0){
//								//清空每个summary中的代理
//								for(WfTaskSummary summary:summaries){
//									wfTaskSummaryDao.clearAgent(summary);
//								}
//							}
						}
					}
				}
				wfAgencyDetailDao.delete(details);
			}
			
		}
	}
	
	/**
	 * 构造一个流程定义id和流程定义名称一一对应的Map
	 * @param wfDefIds 流程定义Id数组
	 * @param wfDefNames 流程定义名称数组
	 * @return 流程定义到流程定义名称的映射
	 */
//	private Map<String, String> buildWfDefMap(String[] wfDefIds, String[] wfDefNames){
//		if(wfDefIds == null || wfDefNames == null){
//			throw new NullPointerException("Parameter wfDefIds, wfDefNames are null");
//		}
//		else if(wfDefIds.length != wfDefNames.length){
//			throw new RuntimeException("The length of wfDefIds is not equal the length of wfDefNames");
//		}
//		else{
//			Map<String, String> wfDefMap = new HashMap<String, String>();
//			for(int i = 0; i < wfDefIds.length; i++){
//				wfDefMap.put(wfDefIds[i], wfDefNames[i]);
//			}
//			return wfDefMap;
//		}
//	}
	
	/**
	 * 添加代理细节
	 * @param agencyId 代理主键 
	 * @param wfDefIds 代理的流程定义id列表
	 * @param wfDefNames 代理的流程定义名称列表
	 */
	private void addAgentDetails(Long agencyId, String[] wfTemplateIds){
		//Map<String, String> wfDefMap = buildWfDefMap(wfDefIds, wfDefNames);
		wfAgencyDetailDao.addAgencyDetails(agencyId, wfTemplateIds);
	}
	
	/**
	 * 更新WF_TASK_Summary表
	 * @param processInstances
	 * @param form
	 */
//	private void updateWfTaskSummary(List<ProcessInstance> processInstances, WfAgencyForm form){
//		if(processInstances != null && processInstances.size() > 0){
//			for(ProcessInstance processInstance: processInstances){
//					
//				List<WfTaskSummary> summaries = wfTaskSummaryService.getByAssigneeAndProcessInstanceId(form.getPrincipal(), processInstance.getId());
//				//更新summary
//				if(summaries != null && summaries.size() > 0){
//					for(WfTaskSummary summary:summaries){
//						wfTaskSummaryDao.setAgent(summary, form);
//					}
//				}
//			}
//		}
//	}
	
	/**
	 * 更新JBPM4_TASK表
	 * @param processInstances
	 * @param form
	 */
	private void updateJbpm4Task(List<ProcessInstance> processInstances, WfAgencyForm form){
		if(processInstances != null && processInstances.size() > 0){
			for(ProcessInstance processInstance: processInstances){
				//获取流程实例下的所有task
				List<Jbpm4Task> tasks = jbpm4TaskDao.getByAssigneeAndProcessInstanceId(form.getPrincipal(), processInstance.getId());
					
				//更新task
				if(tasks != null && tasks.size() > 0){
					for(Jbpm4Task task:tasks){
						jbpm4TaskDao.setAgent(task, form);
						
						Jbpm4HistTask histTask = jbpm4HistTaskDao.get(task.getTaskInstDbid());
						jbpm4HistTaskDao.setAgent(histTask, form);
					}
				}
			}
		}
	}
	
	/**
	 * 保存代理及代理细节
	 * @param form
	 * 
	 */
	public boolean saveAgentAndDetails(WfAgencyForm form){
		if(form != null){
			//修改
			if(form.getId() != null){
				//把JBPM4_TASK表中的代理关系清空
				clearAgentCascade(form);
			}
			
			//重复代理检测
			if(isDuplicateAgentDetect(form))
				return false;
			
			//保存记录到主表Agent
			this.save(form);
			
			
				
			if(StringUtils.isNotBlank(form.getWfTemplateIds()) ){
				String[] wfTemplateIds = form.getWfTemplateIds().split(",");
				//	String[] wfDefNames = form.getWfDefNamesStr().split(",");
					
				//添加代理细节
				addAgentDetails(form.getId(), wfTemplateIds);
					
				for(int i = 0; i < wfTemplateIds.length; i++){
					List<ProcessInstance> processInstances = wfService.getProcInstsByTemplateId(Long.parseLong(wfTemplateIds[i]));
						
					//更新JBPM4_TASK表
					updateJbpm4Task(processInstances, form);
					return true;
					//更新WF_TASK_Summary表
	//				updateWfTaskSummary(processInstances, form);
				}
			}
			
			
		}
		return false;
	}
	
	/**
	 * 删除代理信息并更新Jbpm4Task表
	 * @param ids
	 */
	public void deleteAndUpdateJbpm4TaskTable(Long[] ids){
		if(ids != null && ids.length > 0){
			for(Long id:ids){
				List<WfAgencyDetail> details = wfAgencyDetailDao.getBy(id);
				
				WfAgencyForm form = this.get(id);
				if(details != null && details.size() > 0){
					clearAgentCascade(form);
					wfAgencyDetailDao.delete(details);
				}
				this.delete(id);
			}
		}
	}
	
	/**
	 * 获取系统中所有的用户
	 * @page 分页参数
	 * @form 查询条件
	 * @return Page 对象
	 */
	@Transactional(readOnly = true)
	public Page<OmUserForm> getAllUsers(Page<OmUserForm> page, OmUserForm form){
		// 建立新的分页对象
		Page<OmUser> pg = PageUtils.newPageInstance(page);
		
		StringBuilder hql = new StringBuilder("from OmUser user where 1 = 1");
		List<Object> values = new ArrayList<Object>();
		
		if(form != null){
			if(StringUtils.isNotBlank(form.getUserCode())){
				hql.append(" and user.userCode like ?");
				values.add("%" + form.getUserCode() + "%");
			}
			if(StringUtils.isNotBlank(form.getUserName())){
				hql.append(" and user.userName like ?");
				values.add("%" + form.getUserName() + "%");
			}
		}
		omUserDao.findPage(pg, hql.toString(), values);
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<OmUserForm> list = OmUserConverter.convertToFormList(pg.getResult());
		PageUtils.copy(pg, list, page);
		return page;
	}
	
	/**
	 * 根据taskImpl获取对应的WfAgencyForm对象
	 * @param taskImpl
	 * @return
	 */
	@Transactional(readOnly = true)
	public WfAgencyForm getAgentByTask(TaskImpl taskImpl){
		if(taskImpl != null){
			//String procInstId = taskImpl.getProcessInstance().getId();
			String wfDefId = taskImpl.getProcessInstance().getProcessDefinitionId();
			String strs[] = wfDefId.split("-");
			String wfDefKey = strs[0]; //流程key
			Integer wfDefVersion = Integer.parseInt(strs[1]);//流程版本
			
			String assignee = taskImpl.getAssignee();//委托人
			
			StringBuilder hql = new StringBuilder("select agency from WfAgency agency,WfAgencyDetail detail,WfBusTemplate template");
			hql.append(" where agency.principal =? ");
			hql.append(" and template.wfDefKey =? ");
			hql.append(" and template.wfDefVersion =? ");
			hql.append(" and (? between agency.startDate and agency.endDate)");
			hql.append(" and template.id =detail.wfTemplateId ");
			hql.append(" and detail.agencyId =agency.id ");
			
			List<Object> values = new ArrayList<Object>();
			values.add(assignee);
			values.add(wfDefKey);
			values.add(wfDefVersion);
			values.add(new Date());
			
			WfAgency entity = wfAgencyDao.findUnique(hql.toString(),values);
			
			if(entity != null){
				return WfAgencyConvertor.convertVoToForm(entity);
			}
		}
		return null;
	}
	
	//根据代理人获取委托人列表
	public List<String> getPrincipalsByAgent(String agent){
		return this.wfAgencyDao.getPrincipalsByAgent(agent);
	}
	
	/**
	 * 根据taskImpl获取对应的WfAgencyForm对象
	 * @param taskImpl
	 * @return
	 */
	@Transactional(readOnly = true)
	public WfAgency  getAgentByJbpm4Task(String wfDefId,String assignee){
		WfAgency entity = null;
		if(wfDefId != null && assignee != null){
			
			StringBuilder hql = new StringBuilder("select agency from WfAgency agency, WfAgencyDetail detail ");
			hql.append(" where agency.id = detail.agencyId");
			hql.append(" and agency.principal = ? and detail.wfDefId = ?");
			
		    entity = wfAgencyDao.findUnique(hql.toString(), assignee, wfDefId);
			
		}
		return entity;
	}
	
	private String getTemplateNames(List<WfAgencyDetail> details){
		String wfTemplateNames =null;
		if(details != null && details.size() > 0){
			wfTemplateNames ="";
			for(int i=0;i<details.size();i++){
				WfAgencyDetail detail = details.get(i);
				WfBusTemplateForm form = wfBusTemplateService.get(detail.getWfTemplateId());
				if(i==details.size()-1)
					wfTemplateNames = wfTemplateNames+form.getTemplateName();
				else
					wfTemplateNames = wfTemplateNames+form.getTemplateName() + "、";
			}
		}
		return wfTemplateNames;
	}
	
	private boolean isDuplicateAgentDetect (WfAgencyForm form){
		if(form != null){
			Map<String ,Object> map = new HashMap<String ,Object>();
			
			StringBuffer hql = new StringBuffer("select wfdetail.id from WfAgency ps,WfAgencyDetail wfdetail "
					+ " where ps.principal =:principal and ps.id = wfdetail.agencyId and( ");
			buildCondition(hql,form.getWfTemplateIds());
			hql.append( " )and ((:myStartDate between ps.startDate and ps.endDate) "
				+ " or (:myEndDate between ps.startDate and ps.endDate) "
				+ " or (ps.startDate between :myStartDate and :myEndDate) "
				+ " or (ps.endDate between :myStartDate and :myEndDate) "
				+ " )");
			
			map.put("principal",form.getPrincipal());
			map.put("myStartDate",form.getStartDate());
			map.put("myEndDate",form.getEndDate());
			List<Long> list = this.wfAgencyDao.find(hql.toString(),map);
			if(list != null && list.size() > 0)
				return true;
		}
		return false;
	}
	
	private void buildCondition(StringBuffer hql,String wftemplateIds){
		if(hql != null && StringUtils.isNotBlank(wftemplateIds)){
			String[] strArray = wftemplateIds.split(",");
			Long[]ids = StringUtils.convertStringArrayToLongArray(strArray);
			for(int i=0;i<ids.length;i++){
				if(i== 0)
					hql.append(" wfdetail.wfTemplateId="+ids[i]);
				else
					hql.append(" or wfdetail.wfTemplateId="+ids[i]);
			}
		}
	}
}
